package com.ftg.learn.springbootmq.topic.consumer;

import com.rabbitmq.client.Channel;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Recover;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Component;

import org.springframework.amqp.core.Message;
import java.io.IOException;
import java.util.Map;

/**
 * 通用消息消费者 - 接收所有类型的消息
 */
@Component
public class AllConsumer {

    /**
     * 监听通用队列消息
     *
     * @param message 消息内容
     * @param channel 通道
     * @param tag     消息标签
     * @throws IOException IO异常
     */
    @RabbitListener(queues = "all.queue")
    @Retryable(
            value = {Exception.class}, // 指定需要重试的异常类型
            maxAttempts = 4, // 最大尝试次数（包括第一次调用）
            backoff = @Backoff(delay = 1000, multiplier = 2) // 退避策略：初始延迟1秒，每次重试延迟翻倍
    )
    public void handleAllMessage(Map<String, Object> message, Channel channel,
                                 @Header(AmqpHeaders.DELIVERY_TAG) long tag) throws IOException {
        try {
            System.out.println("通用消费者接收到消息: " + message);
            // 记录所有类型的消息，可用于日志记录或监控

            // 手动确认消息
            channel.basicAck(tag, false);
        } catch (Exception e) {
            System.err.println("处理通用消息时发生错误: " + e.getMessage());
            e.printStackTrace();
            // 拒绝消息并重新入队
            channel.basicNack(tag, false, true);
        }
    }


    /**
     * 订单消息处理重试次数耗尽后的回调方法
     *
     * @param e       异常信息
     * @param message 消息内容
     * @param channel 通道
     * @param tag     消息标签
     */
    @Recover
    public void recoverOrder(RuntimeException e, Map<String, Object> message, Channel channel, Message amqpMessage,
                             @Header(AmqpHeaders.DELIVERY_TAG) long tag) throws IOException {
        System.err.println("订单消息处理重试失败，已达到最大重试次数: " + e.getMessage());

        try {
            // 记录失败的订单消息
//            入死信对列

            // 拒绝消息并让它进入死信队列
            channel.basicNack(tag, false, false);
            System.out.println("订单消息已拒绝并进入死信队列");
        } catch (IOException ioException) {
            System.err.println("处理失败订单消息时发生错误: " + ioException.getMessage());
            ioException.printStackTrace();
        }
    }

}

